﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Data.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace CSharpXDL
{


    /*
      220 Serv-U FTP Server v6.3 for WinSock ready...
user dygod1
331 User name okay, need password.
pass dygod1
230 User logged in, proceed.
size /????????.[????????.1024??????]/[????????-www.dy2018.net]????????HD????????.rmvb
213 912695319
rest 100350 Restarting at 100. Send STORE or RETRIEVE.
pasv
227 Entering Passive Mode (61,160,210,106,7,249)
retr /????????.[????????.1024??????]/[????????-www.dy2018.net]????????HD????????.rmvb
150 Opening ASCII mode data connection for [电影天堂-www.dy2018.net]孤岛惊魂HD国语中字.rmvb (912695319 Bytes).
426 Data connection closed, file transfer [电影天堂-www.dy2018.net]孤岛惊魂HD国语中字.rmvb aborted.

220 Serv-U FTP Server v6.3 for WinSock ready...
user dygod1
331 User name okay, need password.
pass dygod1
230 User logged in, proceed.
type i
200 Type set to I.
rest 100350 Restarting at 100. Send STORE or RETRIEVE.
pasv
227 Entering Passive Mode (61,160,210,106,9,29)
retr /????????.[????????.1024??????]/[????????-www.dy2018.net]????????HD????????.rmvb


     
     */
    class FtpConnect : XDLConnect
    {
        long length;
        long range;
        int StateCode;
        StringBuilder StatusDescription=new StringBuilder();
        internal Uri uri;
        WebHeaderCollection requestHeader;
        WebHeaderCollection responseHeader;
        internal BinaryReader reader;
        Stream stream;
        String serverUri;
        Socket socket;
        String user,pass;
        static String[] ECHOCODES = {"220","331","230","200","350","227" };
        String[] ack ;
        int port;
        String ip;
        public FtpConnect(String serverUri, long range, Socket socket)
        {
            this.serverUri = serverUri;
            this.socket = socket;
            this.range = range;
            uri = new Uri(serverUri);
            ip = uri.Host;
            port = uri.Port;
            stream = new NetworkStream(socket, true);
            String[] up = uri.UserInfo.Split(':');
            user = up[0];
            pass = up[1];
            ack = new String[] { "USER " + user, "PASS " + pass, "TYPE I", "REST "+range,"PASV", "RETR " +Uri.UnescapeDataString ( uri .PathAndQuery)};
        }
        public BinaryReader GetResponseStream()
        {
            return reader;

        }
        public int GetStateCode()
        {

            return StateCode;
        }
        public long ContentLength()
        {
            /*
                   220 Serv-U FTP Server v6.3 for WinSock ready...
                    user dygod1
                    331 User name okay, need password.
                    pass dygod1
                    230 User logged in, proceed.
                    size /????????.[????????.1024??????]/[????????-www.dy2018.net]????????HD????????.rmvb
                    213 912695319
             */
            String[] LECHOCODES = {"220","331","230","213" };
            String[] LACK= { "USER " + user, "PASS " + pass, "SIZE " + (Uri.UnescapeDataString (uri .PathAndQuery))};
            NetworkStream lstream = new NetworkStream(ConnectHelper.ConnectSocket(ip, port, ProtocolType.Tcp));
            StreamWriter writer = new StreamWriter(lstream);
            StreamReader r = new StreamReader(lstream);
            String line = null;
            String[] ls = null;
            String code = null;
            StatusDescription = new StringBuilder(); 
            try
            {
                for (int i = 0; i < LECHOCODES.Length; i++)
                {
                    line = r.ReadLine();
                    
                    StatusDescription.AppendLine(line);
                    Console.WriteLine(StatusDescription);
                    ls = line.Split(' ');
                    code = ls[0];
                    if (code == LECHOCODES[3])
                    {

                        
                        break;
                    }
                    if (LECHOCODES[i] == code)
                    {
                        if (code == LECHOCODES[2]) {

                            foreach (EncodingInfo ei in Encoding.GetEncodings())
                            {
                                Encoding e = ei.GetEncoding();
                                writer = new StreamWriter(lstream,e);
                                writer.WriteLine(LACK[i]);
                                line = r.ReadLine();
                                ls = line.Split(' ');
                                code = ls[0];
                                if (LECHOCODES[3] == code) {
                                    Console.WriteLine(ei.Name);
                                    break;
                                }

                            }


                        }

                        StatusDescription.AppendLine(LACK[i]);
                        writer.WriteLine(LACK[i]);
                        writer.Flush();
                    }
                    else
                    {
                        throw new Exception(StatusDescription.ToString());
                    }

                }
            }
            finally {
                r.Dispose();
                writer.Dispose();
                lstream.Dispose();
            }
            return long.Parse(ls[1]);
        }
        public String GetStatusDescription()
        {
            return StatusDescription.ToString();
        }
        public void Close()
        {
            this.reader.Close();
            this.stream.Close();
           
        }
        void readHeader()
        {
            StreamWriter writer = new StreamWriter(stream);
            StreamReader r = new StreamReader(stream);
            String line = null;
            String[] ls=null;
            String code=null;
            StatusDescription = new StringBuilder();
            try
            {
                for (int i = 0; i < ECHOCODES.Length; i++)
                {
                    line = r.ReadLine();
                    StatusDescription.AppendLine(line);
                    ls = line.Split(' ');
                    code = ls[0];

                    if (ECHOCODES[i] == code)
                    {
                        writer.WriteLine(ack[i]);
                        writer.Flush();
                    }
                    else
                    {
                        throw new Exception(StatusDescription.ToString());
                    }

                }
                if (code != ECHOCODES[4])
                    throw new Exception(StatusDescription.ToString());
            }
            finally {
                r.Dispose();
                writer.Dispose();
                stream.Dispose();
            }
            String[] addr = ls[ls.Length - 1].Replace("(", "").Replace(")", "").Split(','); ;
            ip = addr[0] + "." + addr[1] + "." + addr[2] + "." + addr[3];
            port = (int.Parse(addr[4]) * 256 + int.Parse(addr[5]));
            reader = new BinaryReader(new NetworkStream(ConnectHelper.ConnectSocket(ip, port, ProtocolType.Tcp)));

        }
    }
}
